home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / Pakiet internetowy / Przegladarki internetowe / Mozilla Seamonkey 1.0.5 pl / seamonkey-1.0.5.pl-PL.win32.installer.exe / MAIL.XPI / bin / chrome / messenger.jar / content / messenger / commandglue.js < prev    next >
Encoding:
JavaScript  |  2006-04-08  |  39.3 KB  |  1,199 lines

  1. /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  2.  * ***** BEGIN LICENSE BLOCK *****
  3.  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  4.  *
  5.  * The contents of this file are subject to the Mozilla Public License Version
  6.  * 1.1 (the "License"); you may not use this file except in compliance with
  7.  * the License. You may obtain a copy of the License at
  8.  * http://www.mozilla.org/MPL/
  9.  *
  10.  * Software distributed under the License is distributed on an "AS IS" basis,
  11.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  12.  * for the specific language governing rights and limitations under the
  13.  * License.
  14.  *
  15.  * The Original Code is Mozilla Communicator client code, released
  16.  * March 31, 1998.
  17.  *
  18.  * The Initial Developer of the Original Code is
  19.  * Netscape Communications Corporation.
  20.  * Portions created by the Initial Developer are Copyright (C) 1998-1999
  21.  * the Initial Developer. All Rights Reserved.
  22.  *
  23.  * Contributor(s):
  24.  *   Jan Varga <varga@ku.sk>
  25.  *   Hσkan Waara (hwaara@chello.se)
  26.  *
  27.  * Alternatively, the contents of this file may be used under the terms of
  28.  * either of the GNU General Public License Version 2 or later (the "GPL"),
  29.  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  30.  * in which case the provisions of the GPL or the LGPL are applicable instead
  31.  * of those above. If you wish to allow use of your version of this file only
  32.  * under the terms of either the GPL or the LGPL, and not to allow others to
  33.  * use your version of this file under the terms of the MPL, indicate your
  34.  * decision by deleting the provisions above and replace them with the notice
  35.  * and other provisions required by the GPL or the LGPL. If you do not delete
  36.  * the provisions above, a recipient may use your version of this file under
  37.  * the terms of any one of the MPL, the GPL or the LGPL.
  38.  *
  39.  * ***** END LICENSE BLOCK ***** */
  40.  
  41.  
  42. /*
  43.  * Command-specific code. This stuff should be called by the widgets
  44.  */
  45.  
  46. //NOTE: gMessengerBundle and gBrandBundle must be defined and set
  47. //      for this Overlay to work properly
  48.  
  49. var gFolderJustSwitched = false;
  50. var gBeforeFolderLoadTime;
  51. var gRDFNamespace = "http://www.w3.org/1999/02/22-rdf-syntax-ns#";
  52. var gVirtualFolderTerms;
  53. var gXFVirtualFolderTerms;
  54. var gCurrentVirtualFolderUri;
  55. var gPrevFolderFlags;
  56. var gPrevSelectedFolder;
  57. var gMsgFolderSelected;
  58.  
  59. /* keep in sync with nsMsgFolderFlags.h */
  60. var MSG_FOLDER_FLAG_VIRTUAL = 0x0020;
  61. const MSG_FOLDER_FLAG_TRASH = 0x0100;
  62. const MSG_FOLDER_FLAG_SENTMAIL = 0x0200;
  63. const MSG_FOLDER_FLAG_DRAFTS = 0x0400;
  64. const MSG_FOLDER_FLAG_QUEUE = 0x0800;
  65. const MSG_FOLDER_FLAG_INBOX = 0x1000;
  66. const MSG_FOLDER_FLAG_TEMPLATES = 0x400000;
  67. const MSG_FOLDER_FLAG_JUNK = 0x40000000;
  68.  
  69. function OpenURL(url)
  70. {
  71.   messenger.SetWindow(window, msgWindow);
  72.   messenger.OpenURL(url);
  73. }
  74.  
  75. function GetMsgFolderFromResource(folderResource)
  76. {
  77.   if (!folderResource)
  78.      return null;
  79.  
  80.   var msgFolder = folderResource.QueryInterface(Components.interfaces.nsIMsgFolder);
  81.   if (msgFolder && (msgFolder.parent || msgFolder.isServer))
  82.     return msgFolder;
  83.   else
  84.     return null;
  85. }
  86.  
  87. function GetServer(uri)
  88. {
  89.     if (!uri) return null;
  90.     try {
  91.         var folder = GetMsgFolderFromUri(uri, true);
  92.         return folder.server;
  93.     }
  94.     catch (ex) {
  95.         dump("GetServer("+uri+") failed, ex="+ex+"\n");
  96.     }
  97.     return null;
  98. }
  99.  
  100. function LoadMessageByUri(uri)
  101. {
  102.   //dump("XXX LoadMessageByUri " + uri + " vs " + gCurrentDisplayedMessage + "\n");
  103.   if(uri != gCurrentDisplayedMessage)
  104.   {
  105.         dump("fix this, get the nsIMsgDBHdr and the nsIMsgFolder from the uri...\n");
  106. /*
  107.     var resource = RDF.GetResource(uri);
  108.     var message = resource.QueryInterface(Components.interfaces.nsIMessage);
  109.     if (message)
  110.       setTitleFromFolder(message.msgFolder, message.mimef2DecodedSubject);
  111.  
  112.     var nsIMsgFolder = Components.interfaces.nsIMsgFolder;
  113.     if (message.msgFolder.server.downloadOnBiff)
  114.       message.msgFolder.biffState = nsIMsgFolder.nsMsgBiffState_NoMail;
  115. */
  116.  
  117.     gCurrentDisplayedMessage = uri;
  118.     gHaveLoadedMessage = true;
  119.     OpenURL(uri);
  120.   }
  121.  
  122. }
  123.  
  124. function setTitleFromFolder(msgfolder, subject)
  125. {
  126.     var title = subject || "";
  127.  
  128.     if (msgfolder)
  129.     {
  130.       if (title)
  131.         title += " - ";
  132.  
  133.       title += msgfolder.prettyName;
  134.  
  135.       if (!msgfolder.isServer)
  136.       {
  137.         var server = msgfolder.server;
  138.         var middle;
  139.         var end;
  140.         if (server.type == "nntp") {
  141.           // <folder> on <hostname>
  142.           middle = gMessengerBundle.getString("titleNewsPreHost");
  143.           end = server.hostName;
  144.         } else {
  145.           var identity;
  146.           try {
  147.             var identities = accountManager.GetIdentitiesForServer(server);
  148.  
  149.             identity = identities.QueryElementAt(0, Components.interfaces.nsIMsgIdentity);
  150.             // <folder> for <email>
  151.             middle = gMessengerBundle.getString("titleMailPreHost");
  152.             end = identity.email;
  153.           } catch (ex) {}
  154.         }
  155.         if (middle) title += " " + middle;
  156.         if (end) title += " " + end;
  157.       }
  158.     }
  159.     title += " - " + gBrandBundle.getString("brandShortName");
  160.     document.title = title;
  161. }
  162.  
  163. function UpdateMailToolbar(caller)
  164. {
  165.   //dump("XXX update mail-toolbar " + caller + "\n");
  166.   document.commandDispatcher.updateCommands('mail-toolbar');
  167.  
  168.   // hook for extra toolbar items
  169.   var observerService = Components.classes["@mozilla.org/observer-service;1"].getService(Components.interfaces.nsIObserverService);
  170.   observerService.notifyObservers(window, "mail:updateToolbarItems", null);
  171. }
  172.  
  173. function ChangeFolderByURI(uri, viewType, viewFlags, sortType, sortOrder)
  174. {
  175.   //dump("In ChangeFolderByURI uri = " + uri + " sortType = " + sortType + "\n");
  176.   if (uri == gCurrentLoadingFolderURI)
  177.     return;
  178.  
  179.   SetUpToolbarButtons(uri);
  180.  
  181.   // hook for extra toolbar items
  182.   var observerService = Components.classes["@mozilla.org/observer-service;1"].getService(Components.interfaces.nsIObserverService);
  183.   observerService.notifyObservers(window, "mail:setupToolbarItems", uri);
  184.  
  185.   var resource = RDF.GetResource(uri);
  186.   var msgfolder =
  187.       resource.QueryInterface(Components.interfaces.nsIMsgFolder);
  188.  
  189.   try {
  190.       setTitleFromFolder(msgfolder, null);
  191.   } catch (ex) {
  192.       dump("error setting title: " + ex + "\n");
  193.   }
  194.  
  195.   //if it's a server, clear the threadpane and don't bother trying to load.
  196.   if (msgfolder.isServer) {
  197.     msgWindow.openFolder = null;
  198.  
  199.     ClearThreadPane();
  200.  
  201.     // Load AccountCentral page here.
  202.     ShowAccountCentral();
  203.  
  204.     return;
  205.   }
  206.   else
  207.   {
  208.     if (msgfolder.server.displayStartupPage)
  209.     {
  210.       gDisplayStartupPage = true;
  211.       msgfolder.server.displayStartupPage = false;
  212.     }
  213.   }
  214.  
  215.   // If the user clicks on msgfolder, time to display thread pane and message pane.
  216.   // Hide AccountCentral page
  217.   if (gAccountCentralLoaded)
  218.   {
  219.       HideAccountCentral();
  220.   }
  221.  
  222.   if (gFakeAccountPageLoaded)
  223.   {
  224.       HideFakeAccountPage();
  225.   }
  226.  
  227.   gCurrentLoadingFolderURI = uri;
  228.   gNextMessageAfterDelete = null; // forget what message to select, if any
  229.  
  230.   gCurrentFolderToReroot = uri;
  231.   gCurrentLoadingFolderViewFlags = viewFlags;
  232.   gCurrentLoadingFolderViewType = viewType;
  233.   gCurrentLoadingFolderSortType = sortType;
  234.   gCurrentLoadingFolderSortOrder = sortOrder;
  235.  
  236.   var showMessagesAfterLoading;
  237.   try {
  238.     var server = msgfolder.server;
  239.     if (gPrefBranch.getBoolPref("mail.password_protect_local_cache"))
  240.     {
  241.       showMessagesAfterLoading = server.passwordPromptRequired;
  242.       // servers w/o passwords (like local mail) will always be non-authenticated.
  243.       // So we need to use the account manager for that case.
  244.     }
  245.     else if (server.redirectorType) {
  246.       var prefString = server.type + "." + server.redirectorType + ".showMessagesAfterLoading";
  247.       showMessagesAfterLoading = gPrefBranch.getBoolPref(prefString);
  248.     }
  249.     else
  250.       showMessagesAfterLoading = false;
  251.   }
  252.   catch (ex) {
  253.     showMessagesAfterLoading = false;
  254.   }
  255.  
  256.   if (viewType != nsMsgViewType.eShowVirtualFolderResults && (msgfolder.manyHeadersToDownload || showMessagesAfterLoading))
  257.   {
  258.     gRerootOnFolderLoad = true;
  259.     try
  260.     {
  261.       ClearThreadPane();
  262.       SetBusyCursor(window, true);
  263.       msgfolder.startFolderLoading();
  264.       msgfolder.updateFolder(msgWindow);
  265.     }
  266.     catch(ex)
  267.     {
  268.       SetBusyCursor(window, false);
  269.       dump("Error loading with many headers to download: " + ex + "\n");
  270.     }
  271.   }
  272.   else
  273.   {
  274.     if (viewType != nsMsgViewType.eShowVirtualFolderResults)
  275.       SetBusyCursor(window, true);
  276.     RerootFolder(uri, msgfolder, viewType, viewFlags, sortType, sortOrder);
  277.     gRerootOnFolderLoad = false;
  278.     msgfolder.startFolderLoading();
  279.  
  280.     //Need to do this after rerooting folder.  Otherwise possibility of receiving folder loaded
  281.     //notification before folder has actually changed.
  282.     if (viewType != nsMsgViewType.eShowVirtualFolderResults)
  283.       msgfolder.updateFolder(msgWindow);
  284.   }
  285. }
  286.  
  287. function isNewsURI(uri)
  288. {
  289.   return ((/^news-message:/.test(uri)) || (/^news:/.test(uri)));
  290. }
  291.  
  292. function RerootFolder(uri, newFolder, viewType, viewFlags, sortType, sortOrder)
  293. {
  294.   viewDebug("In reroot folder, sortType = " +  sortType + "viewType = " + viewType + "\n");
  295.   if (sortType == 0)
  296.   {
  297.     try
  298.     {
  299.       var msgdb = newFolder.getMsgDatabase(msgWindow);
  300.       var dbFolderInfo = msgdb.dBFolderInfo;
  301.       sortType = dbFolderInfo.sortType;
  302.       sortOrder = dbFolderInfo.sortOrder;
  303.       viewFlags = dbFolderInfo.viewFlags;
  304.       viewType = dbFolderInfo.viewType;
  305.       dbFolderInfo = null;
  306.     }
  307.     catch(ex)
  308.     {
  309.       dump("invalid db in RerootFolder: " + ex + "\n");
  310.     }
  311.   }
  312.  
  313.   // workaround for #39655
  314.   gFolderJustSwitched = true;
  315.  
  316.   ClearThreadPaneSelection();
  317.  
  318.   //Clear the new messages of the old folder
  319.   var oldFolder = gPrevSelectedFolder;
  320.   if (oldFolder) {
  321.       oldFolder.clearNewMessages();
  322.     oldFolder.hasNewMessages = false;
  323.   }
  324.  
  325.   //Set the window's new open folder.
  326.   msgWindow.openFolder = newFolder;
  327.  
  328.   //the new folder being selected should have its biff state get cleared.
  329.   if(newFolder)
  330.   {
  331.     newFolder.biffState =
  332.           Components.interfaces.nsIMsgFolder.nsMsgBiffState_NoMail;
  333.   }
  334.  
  335.   //Clear out the thread pane so that we can sort it with the new sort id without taking any time.
  336.   // folder.setAttribute('ref', "");
  337.  
  338.   // null this out, so we don't try sort.
  339.   if (gDBView) {
  340.     gDBView.close();
  341.     gDBView = null;
  342.   }
  343.  
  344.   // cancel the pending mark as read timer
  345.   ClearPendingReadTimer();
  346.  
  347.   // if this is the drafts, sent, or send later folder,
  348.   // we show "Recipient" instead of "Author"
  349.   SetSentFolderColumns(IsSpecialFolder(newFolder, MSG_FOLDER_FLAG_SENTMAIL | MSG_FOLDER_FLAG_DRAFTS | MSG_FOLDER_FLAG_QUEUE, true));
  350.   ShowLocationColumn(viewType == nsMsgViewType.eShowVirtualFolderResults);
  351.  
  352.   // now create the db view, which will sort it.
  353.   CreateDBView(newFolder, viewType, viewFlags, sortType, sortOrder);
  354.   if (oldFolder)
  355.   {
  356.     /*disable quick search clear button if we were in the search view on folder switching*/
  357.     disableQuickSearchClearButton();
  358.  
  359.      /*we don't null out the db reference for inbox because inbox is like the "main" folder
  360.        and performance outweighs footprint */
  361.     if (!IsSpecialFolder(oldFolder, MSG_FOLDER_FLAG_INBOX, false))
  362.       if (oldFolder.URI != newFolder.URI)
  363.         oldFolder.setMsgDatabase(null);
  364.   }
  365.   // that should have initialized gDBView, now re-root the thread pane
  366.   RerootThreadPane();
  367.  
  368.   UpdateLocationBar(newFolder);
  369.  
  370.   UpdateStatusMessageCounts(gMsgFolderSelected);
  371.   
  372.   UpdateMailToolbar("reroot folder in 3 pane");
  373.   // hook for extra toolbar items
  374.   var observerService = Components.classes["@mozilla.org/observer-service;1"].getService(Components.interfaces.nsIObserverService);
  375.   observerService.notifyObservers(window, "mail:updateToolbarItems", null);
  376.   // this is to kick off cross-folder searches for virtual folders.
  377.   if (gSearchSession && !gVirtualFolderTerms) // another var might be better...
  378.   {
  379.     viewDebug("doing a xf folder search in rerootFolder\n");
  380.     gDBView.searchSession = gSearchSession;
  381.     gSearchSession.search(msgWindow);
  382.   }
  383. }
  384.  
  385. function SwitchView(command)
  386. {
  387.   // when switching thread views, we might be coming out of quick search
  388.   // or a message view.
  389.   // first set view picker to all
  390.   ViewMessagesBy("viewPickerAll");
  391.  
  392.   // clear the QS text, if we need to
  393.   ClearQSIfNecessary();
  394.   
  395.   // now switch views
  396.   var oldSortType = gDBView ? gDBView.sortType : nsMsgViewSortType.byThread;
  397.   var oldSortOrder = gDBView ? gDBView.sortOrder : nsMsgViewSortOrder.ascending;
  398.   var viewFlags = gDBView ? gDBView.viewFlags : gCurViewFlags;
  399.  
  400.   // close existing view.
  401.   if (gDBView) {
  402.     gDBView.close();
  403.     gDBView = null; 
  404.   }
  405.  
  406.   switch(command)
  407.   {
  408.     case "cmd_viewUnreadMsgs":
  409.  
  410.       viewFlags = viewFlags | nsMsgViewFlagsType.kUnreadOnly;
  411.       CreateDBView(msgWindow.openFolder, nsMsgViewType.eShowAllThreads, viewFlags,
  412.             oldSortType, oldSortOrder );
  413.     break;
  414.     case "cmd_viewAllMsgs":
  415.       viewFlags = viewFlags & ~nsMsgViewFlagsType.kUnreadOnly;
  416.       CreateDBView(msgWindow.openFolder, nsMsgViewType.eShowAllThreads, viewFlags,
  417.             oldSortType, oldSortOrder);
  418.     break;
  419.     case "cmd_viewThreadsWithUnread":
  420.       CreateDBView(msgWindow.openFolder, nsMsgViewType.eShowThreadsWithUnread, nsMsgViewFlagsType.kThreadedDisplay,
  421.             nsMsgViewSortType.byThread, oldSortOrder);
  422.  
  423.     break;
  424.     case "cmd_viewWatchedThreadsWithUnread":
  425.       CreateDBView(msgWindow.openFolder, nsMsgViewType.eShowWatchedThreadsWithUnread, nsMsgViewFlagsType.kThreadedDisplay,
  426.             nsMsgViewSortType.byThread, oldSortOrder);
  427.    break;
  428.     case "cmd_viewIgnoredThreads":
  429.       if (viewFlags & nsMsgViewFlagsType.kShowIgnored)
  430.         viewFlags = viewFlags & ~nsMsgViewFlagsType.kShowIgnored;
  431.       else
  432.         viewFlags = viewFlags | nsMsgViewFlagsType.kShowIgnored;
  433.       CreateDBView(msgWindow.openFolder, nsMsgViewType.eShowAllThreads, viewFlags,
  434.             oldSortType, oldSortOrder);
  435.     break;
  436.   }
  437.  
  438.   RerootThreadPane();
  439.  
  440.   // this is to kick off cross-folder searches for virtual folders.
  441.   if (gSearchSession && !gVirtualFolderTerms) // another var might be better...
  442.   {
  443.     gDBView.searchSession = gSearchSession;
  444.     gSearchSession.search(msgWindow);
  445.   }
  446. }
  447.  
  448. function SetSentFolderColumns(isSentFolder)
  449. {
  450.   var tree = GetThreadTree();
  451.   var searchCriteria = document.getElementById("searchCriteria");
  452.  
  453.   var lastFolderSent = tree.getAttribute("lastfoldersent") == "true";
  454.   if (isSentFolder != lastFolderSent)
  455.   {
  456.     var senderColumn = document.getElementById("senderCol");
  457.     var recipientColumn = document.getElementById("recipientCol");
  458.     
  459.     var saveHidden = senderColumn.getAttribute("hidden");
  460.     senderColumn.setAttribute("hidden", senderColumn.getAttribute("swappedhidden"));
  461.     senderColumn.setAttribute("swappedhidden", saveHidden);
  462.  
  463.     saveHidden = recipientColumn.getAttribute("hidden");
  464.     recipientColumn.setAttribute("hidden", recipientColumn.getAttribute("swappedhidden"));
  465.     recipientColumn.setAttribute("swappedhidden", saveHidden);
  466.   }
  467.  
  468.   if(isSentFolder)
  469.   {
  470.     tree.setAttribute("lastfoldersent", "true");
  471.     searchCriteria.setAttribute("value", gMessengerBundle.getString("recipientSearchCriteria"));
  472.   }
  473.   else
  474.   {
  475.     tree.setAttribute("lastfoldersent", "false");
  476.     searchCriteria.setAttribute("value", gMessengerBundle.getString("senderSearchCriteria"));
  477.   }
  478. }
  479.  
  480. function ShowLocationColumn(show)
  481. {
  482.   var col = document.getElementById("locationCol");
  483.   if (col) {
  484.     if (show) {
  485.       col.removeAttribute("hidden");
  486.       col.removeAttribute("ignoreincolumnpicker");
  487.     }
  488.     else {
  489.       col.setAttribute("hidden","true");
  490.       col.setAttribute("ignoreincolumnpicker","true");
  491.     }
  492.   }
  493. }
  494.  
  495. function SetNewsFolderColumns()
  496. {
  497.   var sizeColumn = document.getElementById("sizeCol");
  498.  
  499.   if (gDBView.usingLines) {
  500.      sizeColumn.setAttribute("tooltiptext",gMessengerBundle.getString("linesColumnTooltip"));
  501.      sizeColumn.setAttribute("label",gMessengerBundle.getString("linesColumnHeader"));
  502.   }
  503.   else {
  504.      sizeColumn.setAttribute("tooltiptext", gMessengerBundle.getString("sizeColumnTooltip"));
  505.      sizeColumn.setAttribute("label", gMessengerBundle.getString("sizeColumnHeader"));
  506.   }
  507. }
  508.  
  509. function UpdateStatusMessageCounts(folder)
  510. {
  511.   var unreadElement = GetUnreadCountElement();
  512.   var totalElement = GetTotalCountElement();
  513.   if(folder && unreadElement && totalElement)
  514.   {
  515.     var numSelected = GetNumSelectedMessages();
  516.  
  517.     var numUnread = (numSelected > 1) ?
  518.             gMessengerBundle.getFormattedString("selectedMsgStatus",
  519.                                                 [numSelected]) :
  520.             gMessengerBundle.getFormattedString("unreadMsgStatus",
  521.                                                 [ folder.getNumUnread(false)]);
  522.     var numTotal =
  523.             gMessengerBundle.getFormattedString("totalMsgStatus",
  524.                                                 [folder.getTotalMessages(false)]);
  525.  
  526.     unreadElement.setAttribute("label", numUnread);
  527.     totalElement.setAttribute("label", numTotal);
  528.     unreadElement.hidden = false;
  529.     totalElement.hidden = false;
  530.  
  531.   }
  532.  
  533. }
  534.  
  535. function ConvertColumnIDToSortType(columnID)
  536. {
  537.   var sortKey;
  538.  
  539.   switch (columnID) {
  540.     case "dateCol":
  541.       sortKey = nsMsgViewSortType.byDate;
  542.       break;
  543.     case "senderCol":
  544.         sortKey = nsMsgViewSortType.byAuthor;
  545.       break;
  546.     case "recipientCol":
  547.         sortKey = nsMsgViewSortType.byRecipient;
  548.       break;
  549.     case "subjectCol":
  550.       sortKey = nsMsgViewSortType.bySubject;
  551.       break;
  552.     case "locationCol":
  553.       sortKey = nsMsgViewSortType.byLocation;
  554.       break;
  555.     case "accountCol":
  556.       sortKey = nsMsgViewSortType.byAccount;
  557.       break;
  558.     case "unreadButtonColHeader":
  559.       sortKey = nsMsgViewSortType.byUnread;
  560.       break;
  561.     case "statusCol":
  562.       sortKey = nsMsgViewSortType.byStatus;
  563.       break;
  564.     case "sizeCol":
  565.       sortKey = nsMsgViewSortType.bySize;
  566.       break;
  567.     case "priorityCol":
  568.       sortKey = nsMsgViewSortType.byPriority;
  569.       break;
  570.     case "flaggedCol":
  571.       sortKey = nsMsgViewSortType.byFlagged;
  572.       break;
  573.     case "threadCol":
  574.       sortKey = nsMsgViewSortType.byThread;
  575.       break;
  576.     case "labelCol":
  577.       sortKey = nsMsgViewSortType.byLabel;
  578.       break;
  579.     case "junkStatusCol":
  580.       sortKey = nsMsgViewSortType.byJunkStatus;
  581.       break;
  582.     case "idCol":
  583.       sortKey = nsMsgViewSortType.byId;
  584.       break;
  585.     case "attachmentCol":
  586.       sortKey = nsMsgViewSortType.byAttachments;
  587.       break;
  588.     default:
  589.       dump("unsupported sort column: " + columnID + "\n");
  590.       sortKey = 0;
  591.       break;
  592.   }
  593.   return sortKey;
  594. }
  595.  
  596. function ConvertSortTypeToColumnID(sortKey)
  597. {
  598.   var columnID;
  599.  
  600.   // hack to turn this into an integer, if it was a string
  601.   // it would be a string if it came from localStore.rdf
  602.   sortKey = sortKey - 0;
  603.  
  604.   switch (sortKey) {
  605.     case nsMsgViewSortType.byDate:
  606.       columnID = "dateCol";
  607.       break;
  608.     case nsMsgViewSortType.byAuthor:
  609.       columnID = "senderCol";
  610.       break;
  611.     case nsMsgViewSortType.byRecipient:
  612.       columnID = "recipientCol";
  613.       break;
  614.     case nsMsgViewSortType.bySubject:
  615.       columnID = "subjectCol";
  616.       break;
  617.     case nsMsgViewSortType.byLocation:
  618.       columnID = "locationCol";
  619.       break;
  620.     case nsMsgViewSortType.byAccount:
  621.       columnID = "accountCol";
  622.       break;
  623.     case nsMsgViewSortType.byUnread:
  624.       columnID = "unreadButtonColHeader";
  625.       break;
  626.     case nsMsgViewSortType.byStatus:
  627.       columnID = "statusCol";
  628.       break;
  629.     case nsMsgViewSortType.byLabel:
  630.       columnID = "labelCol";
  631.       break;
  632.     case nsMsgViewSortType.bySize:
  633.       columnID = "sizeCol";
  634.       break;
  635.     case nsMsgViewSortType.byPriority:
  636.       columnID = "priorityCol";
  637.       break;
  638.     case nsMsgViewSortType.byFlagged:
  639.       columnID = "flaggedCol";
  640.       break;
  641.     case nsMsgViewSortType.byThread:
  642.       columnID = "threadCol";
  643.       break;
  644.     case nsMsgViewSortType.byId:
  645.       columnID = "idCol";
  646.       break;
  647.     case nsMsgViewSortType.byJunkStatus:
  648.       columnID = "junkStatusCol";
  649.       break;
  650.     case nsMsgViewSortType.byAttachments:
  651.       columnID = "attachmentCol";
  652.       break;
  653.     default:
  654.       dump("unsupported sort key: " + sortKey + "\n");
  655.       columnID = null;
  656.       break;
  657.   }
  658.   return columnID;
  659. }
  660.  
  661. var nsMsgViewSortType = Components.interfaces.nsMsgViewSortType;
  662. var nsMsgViewSortOrder = Components.interfaces.nsMsgViewSortOrder;
  663. var nsMsgViewFlagsType = Components.interfaces.nsMsgViewFlagsType;
  664. var nsMsgViewCommandType = Components.interfaces.nsMsgViewCommandType;
  665. var nsMsgViewType = Components.interfaces.nsMsgViewType;
  666. var nsMsgNavigationType = Components.interfaces.nsMsgNavigationType;
  667.  
  668. var gDBView = null;
  669. var gCurViewFlags;
  670. var gCurSortType;
  671.  
  672. // CreateDBView is called when we have a thread pane. CreateBareDBView is called when there is no
  673. // tree associated with the view. CreateDBView will call into CreateBareDBView...
  674.  
  675. function CreateBareDBView(originalView, msgFolder, viewType, viewFlags, sortType, sortOrder)
  676. {
  677.   var dbviewContractId = "@mozilla.org/messenger/msgdbview;1?type=";
  678.   // hack to turn this into an integer, if it was a string
  679.   // it would be a string if it came from localStore.rdf
  680.   viewType = viewType - 0;
  681.  
  682.   switch (viewType) {
  683.       case nsMsgViewType.eShowQuickSearchResults:
  684.           dbviewContractId += "quicksearch";
  685.           break;
  686.       case nsMsgViewType.eShowSearch:
  687.           dbviewContractId += "search";
  688.           break;
  689.       case nsMsgViewType.eShowThreadsWithUnread:
  690.           dbviewContractId += "threadswithunread";
  691.           break;
  692.       case nsMsgViewType.eShowWatchedThreadsWithUnread:
  693.           dbviewContractId += "watchedthreadswithunread";
  694.           break;
  695.       case nsMsgViewType.eShowVirtualFolderResults:
  696.           dbviewContractId += "xfvf";
  697.           break;
  698.       case nsMsgViewType.eShowAllThreads:
  699.       default:
  700.           if (viewFlags & nsMsgViewFlagsType.kGroupBySort)
  701.             dbviewContractId += "group";
  702.           else
  703.             dbviewContractId += "threaded";
  704.           break;
  705.   }
  706.  
  707. //  dump ("contract id = " + dbviewContractId + "original view = " + originalView + "\n");
  708.   if (!originalView)
  709.     gDBView = Components.classes[dbviewContractId].createInstance(Components.interfaces.nsIMsgDBView);
  710.  
  711.   gCurViewFlags = viewFlags;
  712.   var count = new Object;
  713.   if (!gThreadPaneCommandUpdater)
  714.     gThreadPaneCommandUpdater = new nsMsgDBViewCommandUpdater();
  715.  
  716.   gCurSortType = sortType;
  717.  
  718.   if (!originalView) {
  719.     gDBView.init(messenger, msgWindow, gThreadPaneCommandUpdater);
  720.     gDBView.open(msgFolder, gCurSortType, sortOrder, viewFlags, count);
  721.     if (viewType == nsMsgViewType.eShowVirtualFolderResults)
  722.     {
  723.       // the view is a listener on the search results
  724.       gViewSearchListener = gDBView.QueryInterface(Components.interfaces.nsIMsgSearchNotify);
  725.       gSearchSession.registerListener(gViewSearchListener);
  726.     }
  727.   } 
  728.   else {
  729.     gDBView = originalView.cloneDBView(messenger, msgWindow, gThreadPaneCommandUpdater);
  730.   }
  731. }
  732.  
  733. function CreateDBView(msgFolder, viewType, viewFlags, sortType, sortOrder)
  734. {
  735.   // call the inner create method
  736.   CreateBareDBView(null, msgFolder, viewType, viewFlags, sortType, sortOrder);
  737.  
  738.   // now do tree specific work
  739.  
  740.   // based on the collapsed state of the thread pane/message pane splitter,
  741.   // suppress message display if appropriate.
  742.   gDBView.suppressMsgDisplay = IsMessagePaneCollapsed();
  743.  
  744.   UpdateSortIndicators(gCurSortType, sortOrder);
  745. }
  746.  
  747. //------------------------------------------------------------
  748. // Sets the column header sort icon based on the requested
  749. // column and direction.
  750. //
  751. // Notes:
  752. // (1) This function relies on the first part of the
  753. //     <treecell id> matching the <treecol id>.  The treecell
  754. //     id must have a "Header" suffix.
  755. // (2) By changing the "sortDirection" attribute, a different
  756. //     CSS style will be used, thus changing the icon based on
  757. //     the "sortDirection" parameter.
  758. //------------------------------------------------------------
  759. function UpdateSortIndicator(column,sortDirection)
  760. {
  761.   // this is obsolete
  762. }
  763.  
  764. function GetSelectedFolderResource()
  765. {
  766.     var folderTree = GetFolderTree();
  767.     var startIndex = {};
  768.     var endIndex = {};
  769.     folderTree.view.selection.getRangeAt(0, startIndex, endIndex);
  770.     return GetFolderResource(folderTree, startIndex.value);
  771. }
  772.  
  773. function ChangeMessagePaneVisibility(now_hidden)
  774. {
  775.   // we also have to hide the File/Attachments menuitem
  776.   var node = document.getElementById("fileAttachmentMenu");
  777.   if (node)
  778.     node.hidden = now_hidden;
  779.  
  780.   if (gDBView) {
  781.     // clear the subject, collapsing won't automatically do this
  782.     setTitleFromFolder(GetThreadPaneFolder(), null);
  783.     // the collapsed state is the state after we released the mouse 
  784.     // so we take it as it is
  785.     gDBView.suppressMsgDisplay = now_hidden;
  786.     // set the subject, uncollapsing won't automatically do this
  787.     gDBView.loadMessageByUrl("about:blank");
  788.     gDBView.selectionChanged();
  789.   }
  790.   var event = document.createEvent('Events');
  791.   if (now_hidden) {
  792.     event.initEvent('messagepane-hide', false, true);
  793.   }
  794.   else {
  795.     event.initEvent('messagepane-unhide', false, true);
  796.   }
  797.   document.getElementById("messengerWindow").dispatchEvent(event);
  798. }
  799.  
  800. function OnClickThreadAndMessagePaneSplitter()
  801. {
  802.   ChangeMessagePaneVisibility(IsMessagePaneCollapsed());
  803. }
  804.  
  805. function FolderPaneSelectionChange()
  806. {
  807.     var folderTree = GetFolderTree();
  808.     var folderSelection = folderTree.view.selection;
  809.  
  810.     // This prevents a folder from being loaded in the case that the user
  811.     // has right-clicked on a folder different from the one that was
  812.     // originally highlighted.  On a right-click, the highlight (selection)
  813.     // of a row will be different from the value of currentIndex, thus if
  814.     // the currentIndex is not selected, it means the user right-clicked
  815.     // and we don't want to load the contents of the folder.
  816.     if (!folderSelection.isSelected(folderSelection.currentIndex))
  817.       return;
  818.  
  819.     if(gTimelineEnabled) {
  820.       gTimelineService.startTimer("FolderLoading");
  821.       gTimelineService.enter("FolderLoading has Started");
  822.     }
  823.  
  824.     gVirtualFolderTerms = null;
  825.     gXFVirtualFolderTerms = null;
  826.  
  827.     if (folderSelection.count == 1)
  828.     {
  829.         var startIndex = {};
  830.         var endIndex = {};
  831.  
  832.  
  833.         folderSelection.getRangeAt(0, startIndex, endIndex);
  834.         var folderResource = GetFolderResource(folderTree, startIndex.value);
  835.         UpdateLocationBar(folderResource);
  836.         var uriToLoad = folderResource.Value;
  837.         var msgFolder = folderResource.QueryInterface(Components.interfaces.nsIMsgFolder);
  838.         if (msgFolder == gMsgFolderSelected)
  839.            return;
  840.         gPrevSelectedFolder = gMsgFolderSelected;
  841.         gMsgFolderSelected = msgFolder;
  842.         var folderFlags = msgFolder.flags;
  843.         // if this is same folder, and we're not showing a virtual folder
  844.         // then do nothing.
  845.         if (msgFolder == msgWindow.openFolder && 
  846.           !(folderFlags & MSG_FOLDER_FLAG_VIRTUAL) && ! (gPrevFolderFlags & MSG_FOLDER_FLAG_VIRTUAL))
  847.         {
  848.             dump("msgFolder already open" + folderResource.URI + "\n");
  849.             return;
  850.         }
  851.         else
  852.         {
  853.             OnLeavingFolder(gPrevSelectedFolder);  // mark all read in last folder
  854.             var sortType = 0;
  855.             var sortOrder = 0;
  856.             var viewFlags = 0;
  857.             var viewType = 0;
  858.             gVirtualFolderTerms = null;
  859.             gXFVirtualFolderTerms = null;
  860.             gPrevFolderFlags = folderFlags;
  861. //            gSearchInput.showingSearchCriteria = false;
  862.             gCurrentVirtualFolderUri = null;
  863.             // don't get the db if this folder is a server
  864.             // we're going to be display account central
  865.             if (!(msgFolder.isServer)) 
  866.             {
  867.               try 
  868.               {
  869.                 var msgDatabase = msgFolder.getMsgDatabase(msgWindow);
  870.                 if (msgDatabase)
  871.                 {
  872.                   gSearchSession = null;
  873.                   var dbFolderInfo = msgDatabase.dBFolderInfo;
  874.                   sortType = dbFolderInfo.sortType;
  875.                   sortOrder = dbFolderInfo.sortOrder;
  876.                   viewType = dbFolderInfo.viewType;
  877.                   viewFlags = dbFolderInfo.viewFlags;
  878.                   if (folderFlags & MSG_FOLDER_FLAG_VIRTUAL)
  879.                   {
  880.                     viewType = nsMsgViewType.eShowQuickSearchResults;
  881.                     var searchTermString = dbFolderInfo.getCharPtrProperty("searchStr");
  882.                     // trick the view code into updating the real folder...
  883.                     gCurrentVirtualFolderUri = uriToLoad;
  884.                     var srchFolderUri = dbFolderInfo.getCharPtrProperty("searchFolderUri");
  885.                     var srchFolderUriArray = srchFolderUri.split('|');
  886.                     var searchOnline = dbFolderInfo.getBooleanProperty("searchOnline", false);
  887.                     // cross folder search
  888.                     var filterService = Components.classes["@mozilla.org/messenger/services/filters;1"].getService(Components.interfaces.nsIMsgFilterService);
  889.                     var filterList = filterService.getTempFilterList(msgFolder);
  890.                     var tempFilter = filterList.createFilter("temp");
  891.                     filterList.parseCondition(tempFilter, searchTermString);
  892.                     if (srchFolderUriArray.length > 1)
  893.                     {
  894.                       viewType = nsMsgViewType.eShowVirtualFolderResults;
  895.                       gXFVirtualFolderTerms = CreateGroupedSearchTerms(tempFilter.searchTerms);
  896.                       setupXFVirtualFolderSearch(srchFolderUriArray, gXFVirtualFolderTerms, searchOnline);
  897.                       gSearchInput.showingSearchCriteria = false;
  898.                       // need to set things up so that reroot folder issues the search
  899.                     }
  900.                     else
  901.                     {
  902.                       uriToLoad = srchFolderUri;
  903.                       // we need to load the db for the actual folder so that many hdrs to download
  904.                       // will return false...
  905.                       var realFolderRes = GetResourceFromUri(uriToLoad);
  906.                       var realFolder = realFolderRes.QueryInterface(Components.interfaces.nsIMsgFolder);
  907.                       msgDatabase = realFolder.getMsgDatabase(msgWindow);
  908. //                      dump("search term string = " + searchTermString + "\n");
  909.                     
  910.                       gVirtualFolderTerms = CreateGroupedSearchTerms(tempFilter.searchTerms);
  911. //                      gSearchInput.showingSearchCriteria = false;
  912.                     }
  913.                   }
  914.                   msgDatabase = null;
  915.                   dbFolderInfo = null;
  916.                 }
  917.               }
  918.               catch (ex)
  919.               {
  920.                 dump("failed to get view & sort values.  ex = " + ex +"\n");
  921.               }
  922.             }
  923.             if (gDBView && gDBView.viewType == nsMsgViewType.eShowQuickSearchResults)
  924.             {
  925.               if (gPreQuickSearchView) //close cached view before quick search
  926.               {
  927.                 gPreQuickSearchView.close();
  928.                 gPreQuickSearchView = null;  
  929.               }
  930.               var searchInput = document.getElementById("searchInput");  //reset the search input on folder switch
  931.               if (searchInput) 
  932.                 searchInput.value = "";
  933.             }
  934.             ClearMessagePane();
  935.  
  936.             if (gXFVirtualFolderTerms)
  937.               viewType = nsMsgViewType.eShowVirtualFolderResults;
  938.             else if (gSearchEmailAddress || gDefaultSearchViewTerms || gVirtualFolderTerms) 
  939.               viewType = nsMsgViewType.eShowQuickSearchResults;
  940.             else if (viewType == nsMsgViewType.eShowQuickSearchResults)
  941.               viewType = nsMsgViewType.eShowAllThreads;  //override viewType - we don't want to start w/ quick search
  942.             ChangeFolderByURI(uriToLoad, viewType, viewFlags, sortType, sortOrder);
  943.            if (gVirtualFolderTerms)
  944.              gDBView.viewFolder = msgFolder;        
  945.          }
  946.     }
  947.     else
  948.     {
  949.         msgWindow.openFolder = null;
  950.         ClearThreadPane();
  951.     }
  952.  
  953.     if (gAccountCentralLoaded)
  954.       UpdateMailToolbar("gAccountCentralLoaded");
  955.     else if (gFakeAccountPageLoaded)
  956.       UpdateMailToolbar("gFakeAccountPageLoaded");
  957.     else
  958.       document.getElementById('advancedButton').setAttribute("disabled" , !(IsCanSearchMessagesEnabled()));
  959.  
  960.     if (gDisplayStartupPage)
  961.     {
  962.         loadStartPage();
  963.         gDisplayStartupPage = false;
  964.         UpdateMailToolbar("gDisplayStartupPage");
  965.     }    
  966. }
  967.  
  968. function ClearThreadPane()
  969. {
  970.   if (gDBView) {
  971.     gDBView.close();
  972.     gDBView = null; 
  973.   }
  974. }
  975.  
  976. function IsSpecialFolder(msgFolder, flags, checkAncestors)
  977. {
  978.     if (!msgFolder) 
  979.         return false;
  980.     else if ((msgFolder.flags & flags) == 0) 
  981.     {
  982.       var parentMsgFolder = msgFolder.parentMsgFolder;
  983.  
  984.       return (parentMsgFolder && checkAncestors) ? IsSpecialFolder(parentMsgFolder, flags, true) : false;
  985.     }
  986.     else {
  987.         // the user can set their INBOX to be their SENT folder.
  988.         // in that case, we want this folder to act like an INBOX, 
  989.         // and not a SENT folder
  990.         return !((flags & MSG_FOLDER_FLAG_SENTMAIL) && (msgFolder.flags & MSG_FOLDER_FLAG_INBOX));
  991.     }
  992. }
  993.  
  994. function SelectNextMessage(nextMessage)
  995. {
  996.     dump("XXX implement SelectNextMessage()\n");
  997. }
  998.  
  999. function GetSelectTrashUri(folder)
  1000. {
  1001.     if (!folder) return null;
  1002.     var uri = folder.getAttribute('id');
  1003.     var resource = RDF.GetResource(uri);
  1004.     var msgFolder =
  1005.         resource.QueryInterface(Components.interfaces.nsIMsgFolder);
  1006.     if (msgFolder)
  1007.     {
  1008.         var rootFolder = msgFolder.rootFolder;
  1009.         var numFolder;
  1010.         var out = new Object();
  1011.         var trashFolder = rootFolder.getFoldersWithFlag(MSG_FOLDER_FLAG_TRASH, 1, out);
  1012.         numFolder = out.value;
  1013.         if (trashFolder) {
  1014.             return trashFolder.URI;
  1015.         }
  1016.     }
  1017.     return null;
  1018. }
  1019.  
  1020. var mailOfflineObserver = {
  1021.   observe: function(subject, topic, state) {
  1022.     // sanity checks
  1023.     if (topic != "network:offline-status-changed") return;
  1024.     MailOfflineStateChanged(state == "offline");
  1025.   }
  1026. }
  1027.  
  1028. function AddMailOfflineObserver() 
  1029. {
  1030.   var observerService = Components.classes["@mozilla.org/observer-service;1"].getService(Components.interfaces.nsIObserverService); 
  1031.   observerService.addObserver(mailOfflineObserver, "network:offline-status-changed", false);
  1032. }
  1033.  
  1034. function RemoveMailOfflineObserver()
  1035. {
  1036.   var observerService = Components.classes["@mozilla.org/observer-service;1"].getService(Components.interfaces.nsIObserverService); 
  1037.   observerService.removeObserver(mailOfflineObserver,"network:offline-status-changed");
  1038. }
  1039.  
  1040. function getSearchTermString(searchTerms)
  1041. {
  1042.   var searchIndex;
  1043.   var condition = "";
  1044.   var count = searchTerms.Count();
  1045.   for (searchIndex = 0; searchIndex < count; )
  1046.   {
  1047.     var term = searchTerms.QueryElementAt(searchIndex++, Components.interfaces.nsIMsgSearchTerm);
  1048.     
  1049.     if (condition.length > 1)
  1050.       condition += ' ';
  1051.     
  1052.     condition += (term.booleanAnd) ? "AND (" : "OR (";
  1053.     condition += term.termAsString + ')';
  1054.   }
  1055.   return condition;
  1056. }
  1057.  
  1058. function  CreateVirtualFolder(newName, parentFolder, searchFolderURIs, searchTerms, searchOnline)
  1059. {
  1060.   // ### need to make sure view/folder doesn't exist.
  1061.   if (searchFolderURIs && (searchFolderURIs != "") && newName && (newName != "")) 
  1062.   {
  1063.     try
  1064.     {
  1065.       var newFolder = parentFolder.addSubfolder(newName);
  1066.       newFolder.setFlag(MSG_FOLDER_FLAG_VIRTUAL);
  1067.       var vfdb = newFolder.getMsgDatabase(msgWindow);
  1068.       var searchTermString = getSearchTermString(searchTerms);
  1069.       var dbFolderInfo = vfdb.dBFolderInfo;
  1070.       // set the view string as a property of the db folder info
  1071.       // set the original folder name as well.
  1072.       dbFolderInfo.setCharPtrProperty("searchStr", searchTermString);
  1073.       dbFolderInfo.setCharPtrProperty("searchFolderUri", searchFolderURIs);
  1074.       dbFolderInfo.setBooleanProperty("searchOnline", searchOnline);
  1075.       vfdb.summaryValid = true;
  1076.       vfdb.Close(true);
  1077.       parentFolder.NotifyItemAdded(newFolder);
  1078.       var accountManager = Components.classes["@mozilla.org/messenger/account-manager;1"].getService(Components.interfaces.nsIMsgAccountManager);
  1079.       accountManager.saveVirtualFolders();
  1080.     }
  1081.     catch(e)
  1082.     {
  1083.       throw(e); // so that the dialog does not automatically close
  1084.       dump ("Exception : creating virtual folder \n");
  1085.     }
  1086.   }
  1087.   else 
  1088.   {
  1089.     dump("no name or nothing selected\n");
  1090.   }   
  1091. }
  1092.  
  1093. var searchSessionContractID = "@mozilla.org/messenger/searchSession;1";
  1094. var gSearchView;
  1095. var gSearchSession;
  1096.  
  1097. var nsIMsgFolder = Components.interfaces.nsIMsgFolder;
  1098. var nsIMsgWindow = Components.interfaces.nsIMsgWindow;
  1099. var nsIMsgRDFDataSource = Components.interfaces.nsIMsgRDFDataSource;
  1100. var nsMsgSearchScope = Components.interfaces.nsMsgSearchScope;
  1101.  
  1102. var gFolderDatasource;
  1103. var gFolderPicker;
  1104. var gStatusBar = null;
  1105. var gTimelineEnabled = false;
  1106. var gMessengerBundle = null;
  1107.  
  1108. // Datasource search listener -- made global as it has to be registered
  1109. // and unregistered in different functions.
  1110. var gDataSourceSearchListener;
  1111. var gViewSearchListener;
  1112.  
  1113. var gMailSession;
  1114.  
  1115. function GetScopeForFolder(folder) 
  1116. {
  1117.   return folder.server.searchScope;
  1118. }
  1119.  
  1120. function setupXFVirtualFolderSearch(folderUrisToSearch, searchTerms, searchOnline)
  1121. {
  1122.     var count = new Object;
  1123.   var i;
  1124.  
  1125.     gSearchSession = Components.classes[searchSessionContractID].createInstance(Components.interfaces.nsIMsgSearchSession);
  1126.  
  1127.     gMailSession = Components.classes[mailSessionContractID].getService(Components.interfaces.nsIMsgMailSession);
  1128.  
  1129.   for (i in folderUrisToSearch)
  1130.     {
  1131.       var realFolderRes = GetResourceFromUri(folderUrisToSearch[i]);
  1132.       var realFolder = realFolderRes.QueryInterface(Components.interfaces.nsIMsgFolder);
  1133.       if (!realFolder.isServer)
  1134.         gSearchSession.addScopeTerm(!searchOnline ? nsMsgSearchScope.offlineMail : GetScopeForFolder(realFolder), realFolder);
  1135.     }
  1136.  
  1137.     var termsArray = searchTerms.QueryInterface(Components.interfaces.nsISupportsArray);
  1138.   for (i = 0; i < termsArray.Count(); ++i)
  1139.       gSearchSession.appendTerm(termsArray.GetElementAt(i).QueryInterface(Components.interfaces.nsIMsgSearchTerm));
  1140. }
  1141.  
  1142. function CreateGroupedSearchTerms(searchTermsArray)
  1143. {
  1144.  
  1145.   var searchSession = gSearchSession || 
  1146.     Components.classes[searchSessionContractID].createInstance(Components.interfaces.nsIMsgSearchSession);
  1147.  
  1148.   // create a temporary isupports array to store our search terms
  1149.   // since we will be modifying the terms so they work with quick search
  1150.   var searchTermsArrayForQS = Components.classes["@mozilla.org/supports-array;1"].createInstance(Components.interfaces.nsISupportsArray);
  1151.   
  1152.   var numEntries = searchTermsArray.Count();
  1153.   for (var i = 0; i < numEntries; i++) {
  1154.     var searchTerm = searchTermsArray.GetElementAt(i).QueryInterface(Components.interfaces.nsIMsgSearchTerm); 
  1155.  
  1156.     // clone the term, since we might be modifying it
  1157.     var searchTermForQS = searchSession.createTerm();
  1158.     searchTermForQS.value = searchTerm.value;
  1159.     searchTermForQS.attrib = searchTerm.attrib;
  1160.     searchTermForQS.op = searchTerm.op;
  1161.  
  1162.     // mark the first node as a group
  1163.     if (i == 0)
  1164.       searchTermForQS.beginsGrouping = true;
  1165.     else if (i == numEntries - 1)
  1166.       searchTermForQS.endsGrouping = true;
  1167.  
  1168.     // turn the first term to true to work with quick search...
  1169.     searchTermForQS.booleanAnd = i ? searchTerm.booleanAnd : true; 
  1170.     
  1171.     searchTermsArrayForQS.AppendElement(searchTermForQS);
  1172.   }
  1173.   return searchTermsArrayForQS;
  1174. }
  1175.  
  1176. function OnLeavingFolder(aFolder)
  1177. {
  1178.   try
  1179.   {
  1180.     // Mark all messages of aFolder as read:
  1181.     // We can't use the command controller, because it is already tuned in to the
  1182.     // new folder, so we just mimic its behaviour wrt goDoCommand('cmd_markAllRead').
  1183.     if (gDBView && gPrefBranch.getBoolPref("mailnews.mark_message_read." + aFolder.server.type))
  1184.     {
  1185.       gDBView.doCommand(nsMsgViewCommandType.markAllRead);
  1186.     }
  1187.   }
  1188.   catch(e){/* ignore */}
  1189. }
  1190.  
  1191. var gViewDebug = false;
  1192.  
  1193. function viewDebug(str)
  1194. {
  1195.   if (gViewDebug)
  1196.     dump(str);
  1197. }
  1198.  
  1199.